import EventType from "../../module/common/EventType";
import Singleton from "../common/Singleton";
import EventManage from "../event/EventManage";
import PoolObj from "../pool/PoolObj";
import ColorUtils from "../utils/ColorUtils";
import Tween from "./Tween";
import Utils from "../utils/Utils";
import { getPos, itmeSign } from "./PosDefine";
import UIManage from "../gui/UIManage";
import { UILayer } from "../gui/UIDefine";
import Context from "../context/Context";
import { IPos } from "../common/Common";

export type flyRes = () => flySp;
export type popRes = () => popSp;


export class FlyGold extends Singleton {


    static get I() { return this.Instance() }

    private _effArr: [flySp | popSp, Tween<any>][] = [];

    private _minR = 10;
    private _maxR = 100;


    /**
     * 金币飘字
     * @param url 资源
     * @param fo 起点
     * @param to 终点
     * @param num 数量
     * @param sign 标识 方便批量移除
     */
    flyRes(url: string | flyRes, fo: IPos, to: IPos, num: number, sign?: string) {

        num = Math.max(3, Math.min(6, num));

        if (typeof url === "string" && Utils.isNil(Laya.loader.getRes(url))) {
            Laya.loader.load(url, Laya.Handler.create(this, execute.bind(this)));
        } else {
            execute.call(this);
        }


        function execute(this: FlyGold) {
            while (num > 0) {
                let item = this.genFly(url);
                item.sign = sign;
                let twee = this.fly(item, fo, to, num);

                this._effArr.push([item, twee]);
                --num;
            }
        }
    }

    /**
     * 
     * @param url 
     * @param tar 
     * @param str 
     * @param sign 
     */
    popRes(url: string, tar: IPos, str: string, sign?: string) {
        let p = getPos(tar);

        if (typeof url === "string" && Laya.loader.getRes(url) == null) {
            Laya.loader.load(url, Laya.Handler.create(this, execute));
        } else {
            execute.call(this);
        }

        function execute(this: FlyGold) {
            let item = this.genPop(url);
            item.sign = sign;
            item.skin = url;
            item.text = str;
            item.pos(p[0], p[1]);

            this.popCheck(item)
            Context.Instance.get(UIManage).getLayer(UILayer.eff).displayObject.addChild(item);

            // let tween = Laya.Tween.getTween(item);
            let twee = Tween.get(item)
                .to({ y: item.y - 80 }, 300)
                .to({ alpha: 0 }, 800)
                .call(this.onEnd, this, [item]);

            this._effArr.push([item, twee]);
        }
    }


    /**
     * 清理特效
     * @param sign 标识,默认全清
     */
    clearEff(sign?: string) {
        let arr = this._effArr;
        for (let i = 0; i < arr.length; i++) {
            let elm = arr[i];

            if (sign != null && elm[0].sign != sign) continue;
            this.clearItem(elm, i);
            i--;

        }
    }

    private clearItem<T = flySp | popSp>(elm: [T, Tween<T>], index: number) {
        if (elm[0] instanceof flySp) {
            flySp.recover(elm[0]);
            elm[1].clear();
        }

        if (elm[0] instanceof popSp) {
            // this.onEnd(sign,elm[0])
            popSp.recover(elm[0]);
            elm[1].clear();
        }

        this._effArr.splice(index, 1);
    }

    private onEnd(item: flySp | popSp) {

        item instanceof flySp ? flySp.recover(item) : popSp.recover(item);

        let index = this._effArr.findIndex(v => v[0] === item);

        if (index >= 0) {
            this._effArr.splice(index, 1);
        }

        if (item.sign != null) {
            // EventManage.I.event(EventType.FLY_COMPILE, item.sign);
            Context.Instance.get(EventManage).event(EventType.FLY_COMPILE, item.sign);
        }
    }

    private popCheck(p: popSp) {
        for (let i = 0; i < this._effArr.length; i++) {
            let elm = this._effArr[i];
            let item = elm[0];
            if (item instanceof flySp) continue;

            if (Math.abs(p.x - item.x) >= p.width) continue;

            if (Math.abs(p.y - item.y) > 200) continue;


            elm[1] = Tween.once(item)
                .to({ y: item.y - 100, alpha: 0 }, 300)
                .call(this.onEnd, this, [item])
        }
    }

    private fly(item: flySp, fo: IPos, to: IPos, index: number) {
        let start = getPos(fo), end = getPos(to);
        let parent = Context.Instance.get(UIManage).getLayer(UILayer.eff).displayObject;
        item.pos(start[0], start[1]);
        parent.addChild(item);

        let r = Math.random() * (this._maxR - this._minR + 1) + this._minR;
        let angle = Math.random() * 360;
        let x = r * Utils.cos(angle);
        let y = r * Utils.sin(angle);

        return Tween.get(item)
            .set({ scaleX: 0, scaleY: 0 })
            .to({ scaleX: 0.6, scaleY: 0.6 }, 200)
            .to({ x: start[0] + x, y: start[1] + y, scaleX: 1, scaleY: 1 }, 500, Tween.turnEase(Laya.Ease.quintOut))
            .to({ x: end[0], y: end[1] }, 800 + 50 * index, Tween.turnEase(Laya.Ease.backIn))
            // .to({ scaleX: 1.2, scaleY: 1.2 }, 150)
            // .to({ scaleX: 1, scaleY: 1 }, 150)
            .call(this.onEnd, this, [item]);
    }

    private genFly(url: string | flyRes) {
        if (typeof url === "function") {
            return url();
        }

        if (Laya.loader.getRes(url) != null) {
            let item = flySp.create();
            item.pivot(item.width >> 1, item.height >> 1);
            item.skin = url;
            return item;
        }

        throw `resources not loaded and bu url:${url}`;
    }


    private genPop(url: string | popRes) {
        if (typeof url === "function") {
            return url();
        }

        if (Laya.loader.getRes(url) != null) {
            let item = popSp.create();
            item.anchorX = item.anchorY = 0.5;
            item.skin = url;
            return item;
        }

        throw `resources not loaded and bu url:${url}`;
    }
}



class flySp extends Laya.Sprite implements itmeSign {

    static create(): flySp {
        return PoolObj.getItemByClass("_flysp_", flySp);
    }

    static recover(node: flySp) {
        node.removeSelf();
        node.sign = null;
        PoolObj.recover("_flysp_", node);
    }

    //==================

    sign: string;

    private _skin: string;

    set skin(skin: string) {
        if (this._skin === skin) {
            return;
        }
        this.loadImage(skin);

        this.pivotX = this.width >> 1;
        this.pivotY = this.height >> 1
    }

    get skin() {
        return this._skin;
    }

}

class popSp extends Laya.HBox implements itmeSign {

    static create(): popSp {
        let item = PoolObj.getItemByClass("_popsp_", popSp);
        item.alpha = 1;
        return item;
    }

    static recover(node: popSp) {
        node.removeSelf();
        node.sign = null;
        PoolObj.recover("_popsp_", node);
    }

    //==================

    sign: string;

    private _skin: string;

    private sp: Laya.Sprite;
    private lb: Laya.Text;

    constructor() {
        super();

        this.bgColor = ColorUtils.black;
        this.size(120, 30);
        this.sp = new Laya.Sprite();
        this.lb = new Laya.Text();

        let sp = this.sp;
        sp.size(30, 30);


        let lb = this.lb;

        lb.x = 70;
        lb.height = 30;
        lb.fontSize = 22;
        lb.bold = true;
        lb.align = "left";
        lb.valign = "middle";
        lb.color = ColorUtils.white;

        this.addChild(this.sp);
        this.addChild(this.lb);

    }


    set skin(url: string) {
        if (this._skin == url) {
            return;
        }
        this.sp.loadImage(url);
    }

    get skin() {
        return this._skin;
    }

    set text(str: string) {
        this.lb.text = str;
    }

}